// todo:持久化存储服务：安全存储服务类，用于存储敏感数据
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'secure_storage.g.dart';

/// 由Riverpod提供者管理，提供者确保整个应用程序只创建和重用一个实例
// * keys: { }指定在创建SecureStorage实例时预加载到缓存中的键。
@riverpod
Future<SecureStorage> secureStorage(ref) => SecureStorage.getInstance(keys: {
      'token',
      'refreshToken',
      'expire',
      // 'cookie',
      // 'sdkAppId',
      // 'userId',
      // 'sign'
    });

// * SecureStorage类
class SecureStorage {
  static SecureStorage? _instance;
  late final FlutterSecureStorage _flutterSecureStorage;
  final Map<String, String> _cache = {};

  // 私有构造函数，确保外部无法直接实例化
  SecureStorage._(this._flutterSecureStorage);

  /// 使用静态方法获取实例，并从缓存中预加载指定的键值
  static Future<SecureStorage> getInstance({required Set<String> keys}) async {
    // 如果实例已存在，则直接返回
    if (_instance != null) return _instance!;

    // 创建新的实例
    final storage = SecureStorage._(const FlutterSecureStorage());

    // 预加载指定 keys 的数据并存入缓存
    for (var key in keys) {
      final value = await storage._flutterSecureStorage.read(key: key);
      if (value != null) {
        storage._cache[key] = value;
      }
    }
    _instance = storage;
    return storage;
  }

  /// 从缓存中获取值，如果缓存没有，则从存储中读取并更新缓存
  // String get(String key) async {
  //   if (_cache.containsKey(key)) return _cache[key];
  //   final value = await _flutterSecureStorage.read(key: key);
  //   if (value != null) {
  //     _cache[key] = value;
  //   }
  //   return value;
  // }
  String? get(String key) => _cache[key];

  /// 设置缓存值并同步更新到安全存储
  Future<void> set(String key, String value) async {
    _cache[key] = value;
    await _flutterSecureStorage.write(key: key, value: value);
  }

  /// 从缓存和安全存储中删除指定 key
  Future<void> remove(String key) async {
    _cache.remove(key);
    await _flutterSecureStorage.delete(key: key);
  }
}

/// 封装一个获取 token 的方法
Future<String?> fetchToken() async {
  final container = ProviderContainer();
  final secureStorage = await container.read(secureStorageProvider.future);
  return secureStorage.get('token');
}
